#include "G4RunManager.hh"
#include "G4UImanager.hh"
#include "G4VisExecutive.hh"
#include "G4UIExecutive.hh"
#include "QGSP_BERT.hh"
#include "KDM2Globals.hh"
#include "KDM2PhysicsList.hh"
#include "KDM2DetectorConstruction.hh"
#include "KDM2PrimaryGeneratorAction.hh"
#include "KDM2RunAction.hh"
#include "KDM2EventAction.hh"
#include "KDM2SteppingAction.hh"
#include "Randomize.hh"
#include "TFile.h"
#include <sstream>
#include <istream>
using namespace std;

void PrintUsage();

G4String dataFilePath;
G4String eventInterfaceFilePath;
int kaonCount;
G4String kaonPositionFilePath;
int eventNum;
TTree* tree;
bool BHVeto;
TBranch* BHVetoBranch;
bool frontVeto;
TBranch* frontVetoBranch;
bool rearVeto;
TBranch* rearVetoBranch;
bool sideVeto;
TBranch* sideVetoBranch;
bool barrelVeto;
TBranch* barrelVetoBranch;
double photonEnergy;
TBranch* energyBranch;
int maxPhotons = 0;

int main(int argc, char** argv) {
	dataFilePath = "";
	eventInterfaceFilePath = "";
	kaonCount = 0;
	kaonPositionFilePath = "";
	eventNum = -1;
	bool startUI = false;

	for (int i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			if (argv[i][1] == 'h') {
				PrintUsage();
				return 0;
			} else if (argv[i][1] == 'c') {
				i++;
				kaonCount = atoi(argv[i]);
			} else if (argv[i][1] == 'o') {
				i++;
				dataFilePath = argv[i];
			} else if (argv[i][1] == 'e') {
				i++;
				eventInterfaceFilePath = argv[i];
			} else if (argv[i][1] == 'p') {
				i++;
				kaonPositionFilePath = argv[i];
			} else if (argv[i][1] == 'n') {
				i++;
				maxPhotons = atoi(argv[i]);
			} else {
				PrintUsage();
				return 0;
			}
		} else {
			PrintUsage();
			return 0;
		}
	}

	bool proceed = true;

	if (kaonCount == 0) {
		G4cout << "Must enter a kaon count > 0\n";
		proceed = false;
	}
	if (dataFilePath == "") {
		G4cout << "Must provide output file path\n";
		proceed = false;
	}
	if (eventInterfaceFilePath == "") {
		G4cout << "Must provide event interface file path\n";
		proceed = false;
	}
	if (kaonPositionFilePath == "") {
		G4cout << "Must provide kaon position file path\n";
		proceed = false;
	}
	if (maxPhotons == 0) {
		G4cout << "Must provide number of photons per decay > 0\n";
		proceed = false;
	}

	if (!proceed) {
		PrintUsage();
		return 0;
	}

	G4long myseed = 336028;
	CLHEP::HepRandom::setTheSeed(myseed);

	// Make the run manager (runningMan)
	G4RunManager *runningMan = new G4RunManager();

	// Instanciate and initialize user initialization classes
	KDM2DetectorConstruction *construction = new KDM2DetectorConstruction();
	runningMan->SetUserInitialization(construction);

	G4VUserPhysicsList *physics = new QGSP_BERT();
	runningMan->SetUserInitialization(physics);

	// Instanciate and initialize visualization manager
	G4VisManager *visMan = new G4VisExecutive();
	visMan->SetVerboseLevel(1);
	visMan->Initialize();

	// Instanciate and initialize user action classes
	KDM2PrimaryGeneratorAction *generator = new KDM2PrimaryGeneratorAction(eventInterfaceFilePath,
			kaonPositionFilePath, kaonCount);
	runningMan->SetUserAction(generator);

	KDM2RunAction *runAction = new KDM2RunAction();
	runningMan->SetUserAction(runAction);

	KDM2EventAction *eventAction = new KDM2EventAction();
	runningMan->SetUserAction(eventAction);

	KDM2SteppingAction* stepAction = new KDM2SteppingAction();
	runningMan->SetUserAction(stepAction);

	// Initialize run manager
	runningMan->Initialize();

	TFile file(dataFilePath, "recreate");

	// Get pointer to UI manager and UI executive, then start session
	G4UImanager *UIman = G4UImanager::GetUIpointer();
	UIman->ApplyCommand("/run/verbose 0");
	UIman->ApplyCommand("/event/verbose 0");
	UIman->ApplyCommand("/tracking/verbose 0");
	if (startUI) {
		UIman->ApplyCommand("/vis/scene/create");
		UIman->ApplyCommand("/vis/scene/add/trajectories");
		UIman->ApplyCommand("/vis/open OGLIX");
		for (int i = 0; i < 1; i++) {
			UIman->ApplyCommand("/run/beamOn");
		}
		int argcFake = 0;
		G4UIExecutive *ui = new G4UIExecutive(argcFake, argv);
		ui->SessionStart();
		delete ui;
	} else {
		std::stringstream ss;
		ss << "/run/beamOn " << kaonCount * maxPhotons;
		UIman->ApplyCommand(ss.str());
	}

	delete visMan;
	delete runningMan;

	file.Close();

	return 0;
}

void PrintUsage() {
	G4cout << "Usage:\n\t-c KaonCount\n\t-o OutputFilePath"
			<< "\n\t-e EventInterfaceFilePath\n\t-p KaonPositionFilePath"
			<< "\n\t-n NumberOfPhotonsPerDecay\n";
}
